package com.liyongjian.apidoc.mvc;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.liyongjian.apidoc.dal.ApiRepository;
import com.liyongjian.apidoc.dal.ModelRepository;
import com.liyongjian.apidoc.dal.ParamRepository;
import com.liyongjian.apidoc.dal.ResRepository;
import com.liyongjian.apidoc.dal.SysRepository;
import com.liyongjian.apidoc.dal.TestRepository;
import com.liyongjian.apidoc.domain.Api;
import com.liyongjian.apidoc.domain.Model;
import com.liyongjian.apidoc.domain.Param;
import com.liyongjian.apidoc.domain.Res;
import com.liyongjian.apidoc.domain.Sys;
import com.liyongjian.apidoc.domain.Test;
import com.liyongjian.apidoc.domain.enumm.ApiType;
import com.liyongjian.apidoc.domain.enumm.ContentType;
import com.liyongjian.apidoc.domain.enumm.DataType;
import com.liyongjian.apidoc.domain.enumm.LiveDieState;
import com.liyongjian.apidoc.dto.AjaxResponse;
import com.liyongjian.apidoc.dto.SessionUser;
import com.liyongjian.apidoc.exception.ServerException;


@Controller
@RequestMapping("")
public class IndexController extends BaseController {

    @Autowired
    private SysRepository sysRepository;
    @Autowired
    private ApiRepository apiRepository;
    @Autowired
    private ParamRepository paramRepository;
    @Autowired
    private ResRepository resRepository;
    @Autowired
    private ModelRepository modelRepository;
    @Autowired
    private TestRepository testRepository;

    @RequestMapping("index")
    public String download(HttpServletRequest request, HttpServletResponse response,
            ModelMap model) {
        return "index";
    }


    @Transactional
    @ResponseBody
    @RequestMapping("index-save")
    public AjaxResponse index_save(HttpServletRequest request, ApiType type, String url,
            String getParam, String bodyParam, String ret, ModelMap model) {
        AjaxResponse ajax = new AjaxResponse(true);
        SessionUser su = this.getCurrentUser(request);
        String[] urlpath = url.split("\\/");
        if (urlpath.length < 3) {
            throw new ServerException("接口地址有误");
        }
        String serverUrl = urlpath[0] + "/" + urlpath[1] + "/" + urlpath[2];
        Sys sys = sysRepository.findByUserIdAndName(su.getId(), serverUrl);
        if (sys == null) {
            sys = new Sys();
            sys.userId = su.getId();
            sys.name = serverUrl;
        }
        sys.state = LiveDieState.LIVE;
        sysRepository.save(sys);
        String path = url.replace(serverUrl, "");
        Api api = apiRepository.findByUserIdAndTypeAndUrlAndSysId(su.getId(), type, path, sys.id);
        if (api == null) {
            api = new Api();
            api.userId = su.getId();
            api.sysId = sys.id;
            api.type = type;
            api.name = path;
            api.url = path;
        }
        api.paramGet = getParam;
        api.paramBody = bodyParam;
        api.state = LiveDieState.LIVE;
        apiRepository.save(api);
        if (!StringUtils.isEmpty(getParam)) {
            Map<String, Object> map = jsonMapper.fromJson(getParam, Map.class);
            for (String key : map.keySet()) {
                Param param = paramRepository.findByUserIdAndNameAndApiIdAndParentId(su.getId(),
                        key, api.id, 0l);
                if (param == null) {
                    param = new Param();
                    param.sysId = api.sysId;
                    param.modelId = api.modelId;
                    param.apiId = api.id;
                    param.userId = su.getId();
                    param.name = key;
                    param.parentId = 0l;
                    param.contentType = ContentType.GET;
                    param.type = DataType.STRING;
                }
                param.state = LiveDieState.LIVE;
                paramRepository.save(param);
            }
        }
        if (!StringUtils.isEmpty(bodyParam)) {
            if (bodyParam.startsWith("{")) {
                Map<String, Object> bodyMap = jsonMapper.fromJson(bodyParam, Map.class);
                paramSave(su.getId(), null, api.sysId, api.modelId, api.id, 0l, bodyMap);
            } else if (bodyParam.startsWith("[")) {
                List<Map<String, Object>> bodyList = jsonMapper.fromJson(bodyParam, List.class);
                paramSave(su.getId(), null, api.sysId, api.modelId, api.id, 0l, bodyList);
            } else {
                paramSave(su.getId(), null, api.sysId, api.modelId, api.id, 0l, bodyParam);
            }
        }


        if (!StringUtils.isEmpty(ret)) {
            if (ret.startsWith("{")) {
                Map<String, Object> bodyMap = jsonMapper.fromJson(ret, Map.class);
                resSave(su.getId(), null, api.sysId, api.modelId, api.id, 0l, bodyMap);
            } else if (ret.startsWith("[")) {
                List<Map<String, Object>> bodyList = jsonMapper.fromJson(ret, List.class);
                resSave(su.getId(), null, api.sysId, api.modelId, api.id, 0l, bodyList);
            } else {
                resSave(su.getId(), null, api.sysId, api.modelId, api.id, 0l, ret);
            }
        }
        return ajax;
    }


    @Transactional
    @ResponseBody
    @RequestMapping("index-descSave")
    public AjaxResponse index_descsave(HttpServletRequest request, Long id, String type,
            String desc, ModelMap model) {
        AjaxResponse ajax = new AjaxResponse(true);
        if ("REQ".equals(type.toUpperCase())) {
            Param param = paramRepository.findOne(id);
            param.description = desc;
            paramRepository.save(param);
        } else if ("API_DESC".equals(type.toUpperCase())) {
            Api api = apiRepository.findOne(id);
            api.description = desc;
            apiRepository.save(api);
        } else if ("API_NAME".equals(type.toUpperCase())) {
            Api api = apiRepository.findOne(id);
            api.name = desc;
            apiRepository.save(api);
        } else if ("RET".equals(type.toUpperCase())) {
            Res res = resRepository.findOne(id);
            res.description = desc;
            resRepository.save(res);
        }
        return ajax;
    }


    @Transactional
    @ResponseBody
    @RequestMapping("index-menu")
    public AjaxResponse index_menu(HttpServletRequest request, ModelMap model) {
        AjaxResponse ajax = new AjaxResponse(true);
        SessionUser su = this.getCurrentUser(request);
        Map<String, Object> map = new HashMap<>();
        List<Sys> syss = sysRepository.findByUserIdAndState(su.getId(), LiveDieState.LIVE);
        List<Model> models = modelRepository.findByUserIdAndState(su.getId(), LiveDieState.LIVE);
        List<Api> apis = apiRepository.findByUserIdAndState(su.getId(), LiveDieState.LIVE);
        List<Test> tests = testRepository.findByUserIdAndState(su.getId(), LiveDieState.LIVE);
        map.put("syss", syss);
        map.put("models", models);
        map.put("apis", apis);
        map.put("tests", tests);
        return ajax.setObj(map);
    }

    @Transactional
    @ResponseBody
    @RequestMapping("index-remove")
    public AjaxResponse index_remove(HttpServletRequest request, String data, ModelMap model) {
        AjaxResponse ajax = new AjaxResponse(true);
        if (!StringUtils.isEmpty(data)) {
            String[] ds = data.split(",");
            for (String d : ds) {
                String[] is = d.split("_");
                Long id = Long.valueOf(is[1]);
                String type = is[0];
                if ("REQ".equals(type.toUpperCase())) {
                    Param param = paramRepository.findOne(id);
                    param.state = LiveDieState.DIE;
                    paramRepository.save(param);
                } else if ("API".equals(type.toUpperCase())) {
                    Api api = apiRepository.findOne(id);
                    api.state = LiveDieState.DIE;
                    apiRepository.save(api);
                } else if ("RET".equals(type.toUpperCase())) {
                    Res res = resRepository.findOne(id);
                    res.state = LiveDieState.DIE;
                    resRepository.save(res);
                }
            }
        }


        return ajax;
    }

    @ResponseBody
    @RequestMapping("index-url")
    public AjaxResponse index_save(HttpServletRequest request, String url, ApiType type,
            ModelMap model) {
        AjaxResponse ajax = new AjaxResponse(true);
        SessionUser su = this.getCurrentUser(request);
        String[] urlpath = url.split("\\/");
        if (urlpath.length < 3) {
            throw new ServerException("接口地址有误");
        }
        String serverUrl = urlpath[0] + "/" + urlpath[1] + "/" + urlpath[2];
        Sys sys = sysRepository.findByUserIdAndName(su.getId(), serverUrl);
        if (sys == null) {
            throw new ServerException("接口地址有误");
        }
        String path = url.replace(serverUrl, "");
        Api api = apiRepository.findByUserIdAndTypeAndUrlAndSysId(su.getId(), type, path, sys.id);
        if (api == null) {
            throw new ServerException("接口地址有误");
        }
        Map<String, Object> map = new HashMap<>();
        List<Param> params = paramRepository.findByApiIdAndState(api.id, LiveDieState.LIVE);
        List<Res> ress = resRepository.findByApiIdAndState(api.id, LiveDieState.LIVE);
        map.put("params", params);
        map.put("ress", ress);
        map.put("api", api);
        return ajax.setObj(map);
    }


    private void paramSave(Long userId, String name, Long sysId, Long modelId, Long apiId,
            Long parentId, Object objparam) {
        Param param = paramRepository.findByUserIdAndNameAndApiIdAndParentId(userId, name, apiId,
                parentId);
        if (param == null) {
            param = new Param();
            param.sysId = sysId;
            param.modelId = modelId;
            param.apiId = apiId;
            param.userId = userId;
            param.name = name;
            param.parentId = parentId;
            param.contentType = ContentType.BODY_JSON;
        }
        param.state = LiveDieState.LIVE;
        if (List.class.isInstance(objparam)) {
            param.type = DataType.LIST;
            paramRepository.save(param);
            List<Object> list = (List<Object>) objparam;
            for (Object listObj : list) {
                paramSave(userId, null, sysId, modelId, apiId, param.id, listObj);
            }
        } else if (Map.class.isInstance(objparam)) {
            param.type = DataType.MAP;
            paramRepository.save(param);

            Map<String, Object> map = (Map<String, Object>) objparam;
            for (String key : map.keySet()) {
                Object mapObj = map.get(key);
                paramSave(userId, key, sysId, modelId, apiId, param.id, mapObj);
            }
        } else {
            param.type = DataType.STRING;
            paramRepository.save(param);
        }
    }


    private void resSave(Long userId, String name, Long sysId, Long modelId, Long apiId,
            Long parentId, Object objparam) {
        Res param =
                resRepository.findByUserIdAndNameAndApiIdAndParentId(userId, name, apiId, parentId);
        if (param == null) {
            param = new Res();
            param.sysId = sysId;
            param.apiId = apiId;
            param.userId = userId;
            param.name = name;
            param.parentId = parentId;
        }
        param.state = LiveDieState.LIVE;
        if (List.class.isInstance(objparam)) {
            param.type = DataType.LIST;
            resRepository.save(param);
            List<Object> list = (List<Object>) objparam;
            for (Object listObj : list) {
                resSave(userId, null, sysId, modelId, apiId, param.id, listObj);
            }
        } else if (Map.class.isInstance(objparam)) {
            param.type = DataType.MAP;
            resRepository.save(param);

            Map<String, Object> map = (Map<String, Object>) objparam;
            for (String key : map.keySet()) {
                Object mapObj = map.get(key);
                resSave(userId, key, sysId, modelId, apiId, param.id, mapObj);
            }
        } else {
            param.type = DataType.STRING;
            resRepository.save(param);
        }
    }



}
